/**
 * PInvestidorEmpreendimento.java
 * Copyright (C) 2009 Jose Mauro da Silva Sandy
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package persistencia.pessoas;

import java.io.IOException;
import java.sql.*;
import plagio.postgres.ConnectionPostgres;
import negocio.pessoas.InvestidorEmpreendimento;
import java.util.*;
import utils.*;

/**
 *
 * @author jmsandy
 */
public class PInvestidorEmpreendimento {

    //<editor-fold defaultstate="collapsed" desc="Attributes">
    private boolean error = false;
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Acessores">
    public boolean isError(){
        return this.error;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Table Columns">
    static final protected String K_TBL_InvEmp     = "InvestidorEmpreendimento";
    static final protected String K_COL_cod_objeto     = "cod_objeto";
    static final protected String K_COL_investidor     = "investidor";
    static final protected String K_COL_empreendimento = "empreendimento";
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Constructor">
    /**
     * Construtor padrao. Responsavel por realizar a persistencia de um
     * relacao investidor e empreendimento
     * @throws java.io.IOException
     */
    public PInvestidorEmpreendimento() throws IOException{
        error = false;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Methods">
    // Realiza a construcao basica de um select
    private StringBuilder formSelector(){
        StringBuilder query = new StringBuilder();
        query.append("SELECT " + K_COL_cod_objeto + ", " + K_COL_investidor +
               ", " + K_COL_empreendimento +" FROM " + "\"" +
               K_TBL_InvEmp + "\"");
        return query;
    }

    /**
     * Responsavel por criar a estrutura para inserir o objeto
     * @return construtor do objeto a ser inserido
     */
    @SuppressWarnings("static-access")
    public String formInsert(){
        return "INSERT INTO \"" + K_TBL_InvEmp + "\"(" + K_COL_cod_objeto +
              ", " + K_COL_investidor + ", " + K_COL_empreendimento +
              ") VALUES (?, ?, ?)";
    }

    /**
     * Responsavel por criar a estrutura para deletar o objeto
     * @param obj - Objeto a ser deletado na base de dados
     * @return construtor do objeto a ser deletado
     */
    public String formDelete(InvestidorEmpreendimento obj){
        return "DELETE FROM \"" + K_TBL_InvEmp + "\" WHERE " + K_COL_cod_objeto
                + " = '" + obj.getCod_objeto() + "'";
    }

    /**
     * Responsavel por inserir um objeto na base de dados
     * @param obj - objeto a ser inserido na base de dados
     * @return TRUE - caso afirmativo e FALSE - caso contrario
     */
    public Boolean insert(InvestidorEmpreendimento obj){
        Boolean status = true;

        try{
            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();

            // Monta o objeto em uma instrucao SQL para insercao no banco
            PreparedStatement stat;
            String query = formInsert();
            stat = conn.getConnection().prepareStatement(query);
            stat.setString(1, obj.getCod_objeto());
            stat.setString(2, obj.getInvestidor());
            stat.setString(3, obj.getEmpreendimento());
            stat.executeUpdate();
            stat.close();
            conn.closeConnection();
        }
        catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            status = false;
        }
        return status;
    }

    /**
     * Responsavel por inserir um objeto na base de dados
     * @param obj - objeto a ser inserido na base de dados
     * @return TRUE - caso afirmativo e FALSE - caso contrario
     */
    public Boolean atualizarBase(ArrayList<InvestidorEmpreendimento> lst)
                                                            throws SQLException{
        Boolean status = true;
        ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

        try{
            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();
            conn.getConnection().setAutoCommit(false);
            // Monta o objeto em uma instrucao SQL para insercao no banco
            PreparedStatement stat = null;
            String insert = formInsert();

            for(InvestidorEmpreendimento obj : lst){
                if(!obj.getWasDeleted()){
                    stat = conn.getConnection().prepareStatement(insert);
                    stat.setString(1, obj.getCod_objeto());
                    stat.setString(2, obj.getInvestidor());
                    stat.setString(3, obj.getEmpreendimento());
                    stat.executeUpdate();
                }
                else{
                    String query = formDelete(obj);
                    stat = conn.getConnection().prepareStatement(query);
                    stat.executeUpdate();
                }
            }
            stat.close();
            conn.getConnection().commit();
            conn.closeConnection();
        }
        catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            status = false;
            conn.getConnection().rollback();
        }
        return status;
    }

    /**
     * Responsavel por atualizar a base de dados
     * @param lst - objeto a ser atualizado na base
     * @return TRUE - caso afirmativo e FALSE - caso contrario
     */
    public Boolean delete(InvestidorEmpreendimento obj){
        Boolean status = true;

        try{
            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();

            // Monta o objeto em uma instrucao SQL para atualizacao no banco
            PreparedStatement stat;
            String query = formDelete(obj);
            stat = conn.getConnection().prepareStatement(query);
            stat.executeUpdate();
            stat.close();
            conn.closeConnection();
        }
        catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            status = false;
        }
        return status;
    }

    /**
     * Recupera um objeto InvestidorEmpreendimento pelo codigo informado
     * @param cod_objeto codigo do investidorEmpreendimento a ser procurada
     * @return o investidorEmpreendimento encontrado ou NULL
     */
    public InvestidorEmpreendimento refresh(String cod_objeto, String className){
        // objeto de retorno
        InvestidorEmpreendimento invEmp = new InvestidorEmpreendimento();

        StringBuilder query = this.formSelector();
        // Clausula where
        query.append(" WHERE " + K_COL_cod_objeto + " = '" + cod_objeto + "'");

        try{
            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();

            Statement stat = conn.getConnection().createStatement();

            // Verifica a existencia do registro de retorno
            ArrayList<InvestidorEmpreendimento> lstInvEmp;
            lstInvEmp = new ArrayList<InvestidorEmpreendimento>();
            lstInvEmp = mapear(stat.executeQuery(query.toString()));
            if(lstInvEmp.size() > 0) invEmp = lstInvEmp.get(0);
            else invEmp = null;

        }
        catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            invEmp = null;
        }
        return invEmp;
    }

    /**
     * Verifica se existe um investidor para um investimento
     * @param idEmpreendimento identificador do empreendimento
     * @return TRUE se existe algum investidor e FALSE caso contrario
     */
    public Boolean existsInv(String idEmpreendimento){
        Boolean ret = false;
        try{
            StringBuilder query = new StringBuilder();
            query.append("SELECT " + K_COL_cod_objeto + " FROM \"");
            query.append(K_TBL_InvEmp + "\" WHERE " + K_COL_empreendimento);
            query.append(" = '" + idEmpreendimento + "'");

            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();

            Statement stat = conn.getConnection().createStatement();


            ret = stat.executeQuery(query.toString()).next();
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
        }
        return ret;
    }

    /**
     * Verifica se existe um empreendimento para um investidor
     * @param idInvestidor identificador do investidor
     * @return TRUE se existe algum investidor e FALSE caso contrario
     */
    public Boolean existsEmp(String idInvestidor){
        Boolean ret = false;
        try{
            StringBuilder query = new StringBuilder();
            query.append("SELECT " + K_COL_cod_objeto + " FROM \"");
            query.append(K_TBL_InvEmp + "\" WHERE " + K_COL_investidor);
            query.append(" = '" + idInvestidor + "'");

            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();

            Statement stat = conn.getConnection().createStatement();

            ret = stat.executeQuery(query.toString()).next();
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
        }
        return ret;
    }

    /**
     * Recupera um lista de relacionamentos para um dado investidor
     * @param idInv identificador do investidor
     * @return lista contendo todos os relacionamentos de um investidor
     */
    public ArrayList<InvestidorEmpreendimento> recLstInvEmp(String idInv){
        // objeto de retorno
        ArrayList<InvestidorEmpreendimento> lstInvEmp;
        lstInvEmp = new ArrayList<InvestidorEmpreendimento>();

        StringBuilder query = this.formSelector();
        // Clausula where
        query.append(" WHERE " + K_COL_investidor + " IN (SELECT ");
        query.append(PInvestidor.K_COL_cod_objeto + " FROM \"");
        query.append(PInvestidor.K_TBL_Investidor + "\" WHERE ");
        query.append(PInvestidor.K_COL_pessoa + " = '" + idInv + "') AND ");
        query.append(K_COL_empreendimento + " IN (SELECT " + K_COL_cod_objeto);
        query.append(" FROM \"" + PEmpreendimento.K_TBL_Empreendimento + "\" ");
        query.append("WHERE " + PEmpreendimento.K_COL_status + " = ");
        query.append(StatusEmpreendimento.ABERTO + ")");

        try{
            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();

            Statement stat = conn.getConnection().createStatement();

            // Verifica a existencia do registro de retorno
            lstInvEmp = mapear(stat.executeQuery(query.toString()));

        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            lstInvEmp = null;
        }
        return lstInvEmp;
    }

    /**
     * Recupera um lista de investidores para um dada empreendimento
     * @param idEmp identificador do empreendimento
     * @return lista contendo todos os relacionamentos de um empreendimento
     */
    public ArrayList<InvestidorEmpreendimento> recLstEmpInv(String idEmp){
        // objeto de retorno
        ArrayList<InvestidorEmpreendimento> lstInvEmp;
        lstInvEmp = new ArrayList<InvestidorEmpreendimento>();

        StringBuilder query = this.formSelector();
        // Clausula where
        query.append(" WHERE " + K_COL_empreendimento + " = '" + idEmp + "'");

        try{
            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();
            Statement stat = conn.getConnection().createStatement();
            // Verifica a existencia do registro de retorno
            lstInvEmp = mapear(stat.executeQuery(query.toString()));
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            lstInvEmp = null;
        }
        return lstInvEmp;
    }

    /**
     * Busca uma lista de contas pagas para um dado investidor
     * @param idEmp identificador do empreendimento
     * @return lista contendo todos os investidores que pagou alguma conta
     *         de um empreendimento.
     */
    public ArrayList<InvestidorEmpreendimento> recLstDivLucro(String idEmp){
        // objeto de retorno
        ArrayList<InvestidorEmpreendimento> lstInvEmp;
        lstInvEmp = new ArrayList<InvestidorEmpreendimento>();

        StringBuilder query = new StringBuilder();
        // Clausula where
        query.append("SELECT c.investidor, e.cod_objeto ");
        query.append("FROM \"ContasPagar\" c, \"Empreendimento\" e, ");
        query.append("\"Nota\" n WHERE e.cod_objeto = n.empreendimento AND ");
        query.append("n.cod_objeto = c.nota AND e.status = 2 AND ");
        query.append("e.cod_objeto = '" + idEmp + "' GROUP BY c.investidor,");
        query.append(" e.cod_objeto");

        try{
            ConnectionPostgres conn = new ConnectionPostgres(); // nova conexao

            // Realiza a conexao com o servidor
            conn = ConnectionSystem.connectionSystem();
            Statement stat = conn.getConnection().createStatement();
            // Verifica a existencia do registro de retorno
            lstInvEmp = mapearAux(stat.executeQuery(query.toString()));
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            error = true;
            lstInvEmp = null;
        }
        return lstInvEmp;
    }

    /**
     * Responsavel por converter o objeto vindo do banco de dados para um
     * modelo de objeto
     * @param result - result que obtem toda lista recebida do servidor
     * @return os objetos mapeados
     * @throws java.sql.SQLException
     */
    private ArrayList<InvestidorEmpreendimento> mapear(ResultSet result)
                                                            throws SQLException{
        ArrayList<InvestidorEmpreendimento> lstInvEmp;
        lstInvEmp = new ArrayList<InvestidorEmpreendimento>();

        // Converte todo result recebido para uma lista de objetos
        while(result.next()){
            InvestidorEmpreendimento invEmp = new InvestidorEmpreendimento();
            invEmp.setCod_objeto(result.getString(1));
            invEmp.setInvestidor(result.getString(2));
            invEmp.setEmpreendimento(result.getString(3));
            invEmp.setIsNew(false);

            lstInvEmp.add(invEmp);
        }
        return lstInvEmp;
    }

    /**
     * Responsavel por converter o objeto vindo do banco de dados para um
     * modelo de objeto
     * @param result - result que obtem toda lista recebida do servidor
     * @return os objetos mapeados
     * @throws java.sql.SQLException
     */
    private ArrayList<InvestidorEmpreendimento> mapearAux(ResultSet result)
                                                            throws SQLException{
        ArrayList<InvestidorEmpreendimento> lstInvEmp;
        lstInvEmp = new ArrayList<InvestidorEmpreendimento>();

        // Converte todo result recebido para uma lista de objetos
        while(result.next()){
            InvestidorEmpreendimento invEmp = new InvestidorEmpreendimento();
            invEmp.setCod_objeto("-1");
            invEmp.setInvestidor(result.getString(1));
            invEmp.setEmpreendimento(result.getString(2));
            invEmp.setIsNew(false);

            lstInvEmp.add(invEmp);
        }
        return lstInvEmp;
    }
    //</editor-fold>    
}